package com.wxxymaker.edu.utils;

import com.blade.kit.EncryptKit;
import com.blade.kit.UUID;
import com.blade.mvc.WebContext;
import com.wxxymaker.edu.model.dao.UserTokenDao;
import com.wxxymaker.edu.model.entity.User;
import com.wxxymaker.edu.model.entity.UserToken;

import java.time.Instant;

/**
 * @AUTHOR soft
 * @DATE 2018/9/4 17:04
 * @DESCRIBE token工具
 */
public class TokenUtils {
    /**
     * 从session中获取当前登录的用户
     * @return 当前登录用户
     */
    public static User currentUser() {
        return WebContext.request().session().attribute(Const.USER_KEY);
    }

    public static UserToken create(User user) {
        return create(user, Const.tokenLimit);
    }

    /**
     * 根据用户信息和指定的token生存期创建token
     * @param user 用户信息
     * @param day  生存时间
     * @return userToken对象,失败null
     */
    public static UserToken create(User user, long day) {
        UserTokenDao dao = getUserTokenDao();

        UserToken token = dao.byUser(user); // 为了避免出现重复的token
        if (token != null) {
            if (!TimeUtils.isOverTime(token.getEndTime())) {
                token.setEndTime(TimeUtils.getTime(Const.tokenLimit));
                dao.change(token);
                return token;
            } else {
                dao.delete(token.getId());
            }
        }
        String uuid     = UUID.captchaChar(16);
        long   second   = Instant.now().getEpochSecond();
        String username = user.getUsername();
        String sha256   = EncryptKit.SHA256(uuid + second +
                "_" + username).toUpperCase();

        UserToken userToken = new UserToken();
        userToken.setToken(sha256);
        userToken.setUserId(user.getId());
        return dao.add(userToken, day);
    }

    /**
     * 认证token
     * 如果token存在,但是已经过期(认证失败),这时会从数据库中删除该token记录
     * @param token 需要认证的token
     * @return 验证成功则返回包涵用户信息的userToken对象,否则null
     */
    public static UserToken auth(String token) {
        if (token == null) return null;
        UserTokenDao dao = getUserTokenDao();
        UserToken userToken = dao.byToken(token, true);

        if (userToken != null) {
            String endTime    = userToken.getEndTime();
            if (!TimeUtils.isOverTime(endTime)) {
                return userToken;
            }
            dao.delete(userToken.getId());
        }
        return null;
    }

    /**
     * 通过token值获没有到期的用户信息
     * @param token token值
     * @return 用户对象
     */
    public static User getNoOverUserByToken(String token) {
        UserTokenDao dao = getUserTokenDao();

        UserToken userToken = dao.byToken(token, true);
        if (userToken != null && !TimeUtils.isOverTime(userToken.getEndTime()))
            return userToken.getUser();
        return null;
    }

    /**
     * 清理所有过期的token
     */
    public static void clearOverTimeToken() {
        UserTokenDao dao = getUserTokenDao();
        dao.getFormOverTime()
                .stream()
                .map(UserToken::getId)
                .forEach(dao::delete);
    }

    private static UserTokenDao getUserTokenDao() {
        return WebContext.blade().ioc().getBean(UserTokenDao.class);
    }
}
